<template>
  <div>
    <!-- 查询区域 -->
    <div class="card" style="margin-bottom: 5px">
      <component
          v-for="(item, index) in searchSchema"
          :key="index"
          :is="item.type === 'select' ? 'el-select' : 'el-input'"
          v-model="searchForm[item.model]"
          v-bind="item.props"
          style="margin-right: 10px; width: 240px"
      >
        <el-option
            v-if="item.type === 'select'"
            v-for="opt in item.options"
            :key="opt.value"
            :label="opt.label"
            :value="opt.value"
        />
      </component>
      <el-button type="primary" @click="handleSearch">查询</el-button>
      <el-button type="warning" @click="handleReset">重置</el-button>
    </div>

    <!-- 操作按钮 -->
    <div class="card" style="margin-bottom: 5px">
      <slot name="actions">
        <el-button type="primary" @click="handleAdd">新增</el-button>
        <el-button type="warning" @click="handleBatchDelete">批量删除</el-button>
      </slot>
    </div>

    <!-- 表格展示 -->
    <div class="card">
      <el-table
          :data="tableData"
          style="width: 100%"
          @selection-change="handleSelectionChange"
      >
        <el-table-column v-if="enableSelection" type="selection" width="55" />
        <!-- 关键：把 width 强制传给 el-table-column -->
        <template v-for="col in columns" :key="col.prop || col.label">
          <el-table-column
              v-if="!col.slot"
              v-bind="col"
              :width="col.width"
              :min-width="col.minWidth"
              :fixed="col.fixed"
          />
          <el-table-column
              v-else
              :label="col.label"
              :width="col.width"
              :min-width="col.minWidth"
              :fixed="col.fixed"
              :align="col.align"
              :class-name="col.className"
          >
            <template #default="scope">
              <slot :name="col.slot" :row="scope.row" />
            </template>
          </el-table-column>
        </template>

        <el-table-column label="操作" width="150" align="center" fixed="right">
          <template #default="scope">
            <el-button type="info" size="small" link @click="handleInfo(scope.row)">详情</el-button>
            <el-button type="primary" size="small" link @click="handleEdit(scope.row)">编辑</el-button>
            <el-button type="danger" size="small" link @click="handleDelete(scope.row.id)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <div style="margin-top: 15px">
        <el-pagination
            v-model:current-page="pageNum"
            v-model:page-size="pageSize"
            :total="total"
            :page-sizes="[5, 10, 15, 20]"
            layout="total, sizes, prev, pager, next, jumper"
            background
            @size-change="fetchData"
            @current-change="fetchData"
        />
      </div>
    </div>

    <!-- 弹窗 -->
    <component
        :is="dialogComponent"
        v-if="dialogComponent"
        v-bind="dialogProps"
        :dialog-visible="dialogVisible"
        :form="dialogForm"
        :mode="dialogMode"
        @update:dialogVisible="val => dialogVisible = val"
        @submit-success="handleSubmitSuccess"
    />
  </div>
</template>

<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'

const props = defineProps({
  columns: Array,
  searchSchema: Array,
  request: Function,
  addFn: Function,
  updateFn: Function,
  deleteFn: Function,
  dialogComponent: Object,
  enableSelection: { type: Boolean, default: false },
  /* 新增：透传给弹窗的额外 props（例如 disabledFields / disabledInEdit 等） */
  dialogProps: { type: Object, default: () => ({}) }
})

const emit = defineEmits(['submit-success'])

const tableData = ref([])
const total = ref(0)
const pageNum = ref(1)
const pageSize = ref(10)
const selectedIds = ref([])
const searchForm = reactive({})
const dialogVisible = ref(false)
const dialogForm = ref({})
const dialogMode = ref('add')

const fetchData = () => {
  props
      .request({
        pageNum: pageNum.value,
        pageSize: pageSize.value,
        ...searchForm
      })
      .then(res => {
        tableData.value = res.data.records || res.data.list || []
        total.value = res.data.total || 0
      })
      .catch(() => ElMessage.error('获取数据失败'))
}

const handleSearch = () => {
  pageNum.value = 1
  fetchData()
}

const handleReset = () => {
  Object.keys(searchForm).forEach(k => (searchForm[k] = ''))
  handleSearch()
}

const handleSelectionChange = val => (selectedIds.value = val.map(r => r.id))

const handleDelete = id =>
    ElMessageBox.confirm('确认删除这条记录吗？', '提示', { type: 'warning' })
        .then(() => props.deleteFn(id))
        .then(() => {
          ElMessage.success('删除成功')
          fetchData()
        })
        .catch(() => {})

const handleBatchDelete = () => {
  if (!selectedIds.value.length) return ElMessage.warning('请至少选择一条记录')
  ElMessageBox.confirm(`确认删除选中的 ${selectedIds.value.length} 条记录吗？`, '提示', { type: 'warning' })
      .then(() => props.deleteFn(selectedIds.value))
      .then(() => {
        ElMessage.success('批量删除成功')
        selectedIds.value = []
        fetchData()
      })
      .catch(() => {})
}

const handleAdd = () => {
  dialogMode.value = 'add'
  dialogForm.value = {}
  dialogVisible.value = true
}

const handleEdit = row => {
  dialogMode.value = 'edit'
  dialogForm.value = { ...row }
  dialogVisible.value = true
}

const handleInfo = row => {
  dialogMode.value = 'info'
  dialogForm.value = { ...row }
  dialogVisible.value = true
}

const handleSubmitSuccess = form => {
  const fn = form.mode === 'add' ? props.addFn : props.updateFn
  const msg = form.mode === 'add' ? '新增成功' : '编辑成功'
  fn(form)
      .then(() => {
        ElMessage.success(msg)
        dialogVisible.value = false
        fetchData()
        emit('submit-success')
      })
      .catch(() => ElMessage.error('操作失败'))
}

onMounted(fetchData)
</script>

<style scoped>
.card {
  padding: 10px;
  background: #fff;
  border-radius: 4px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  margin-bottom: 10px;
}
</style>